package com.javaframe.role.security.intercept;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.intercept.web.FilterInvocation;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

public class RdbmsFilterInvocationDefinitionSource extends JdbcDaoSupport
		implements FilterInvocationDefinitionSource {

	private RdbmsFilterInvocationDefinition rdbmsFilterInvocationDefinition;

	private PathMatcher pathMatcher = new AntPathMatcher();

	public ConfigAttributeDefinition getAttributes(Object object)
			throws IllegalArgumentException {
		if ((object == null) || !this.supports(object.getClass())) {
			throw new IllegalArgumentException(
					"Object must be a FilterInvocation");
		}

		String url = ((FilterInvocation) object).getRequestUrl();
	
		return this.lookupAttributes(url);
	}

	@Override
	protected void initDao() throws Exception {
		this.rdbmsFilterInvocationDefinition = new RdbmsFilterInvocationDefinition(
				this.getDataSource());
	}

	public ConfigAttributeDefinition lookupAttributes(String url) {
		if(logger.isDebugEnabled()){
			logger.debug("lookup Attributes for "+url);
		}
		List<RdbmsEntryHolder> hodlers = getRdbmsEntryHolderList();
		if (hodlers == null || hodlers.size() == 0) {
			return null;
		}
		int firstQuestionMarkIndex = url.indexOf("?");

		if (firstQuestionMarkIndex != -1) {
			url = url.substring(0, firstQuestionMarkIndex);
		}

		Iterator<RdbmsEntryHolder> ite = hodlers.iterator();
		while (ite.hasNext()) {
			RdbmsEntryHolder holder = ite.next();
			boolean matched = pathMatcher.match(holder.getUrl(), url);
			if (matched) {
				return holder.getConfigAttributeDefinition();
			}
		}
		return null;
	}

	public boolean supports(Class clazz) {
		return FilterInvocation.class.isAssignableFrom(clazz);
	}

	public Iterator getConfigAttributeDefinitions() {
		Set<ConfigAttributeDefinition> cads=new HashSet<ConfigAttributeDefinition>();
		List<RdbmsEntryHolder> hodlers = getRdbmsEntryHolderList();
		Iterator<RdbmsEntryHolder> ite = hodlers.iterator();
		while (ite.hasNext()) {
			 cads.add(ite.next().getConfigAttributeDefinition());
		}
		return cads.iterator();
	}

	public RdbmsFilterInvocationDefinition getRdbmsFilterInvocationDefinition() {
		return rdbmsFilterInvocationDefinition;
	}

	public void setRdbmsFilterInvocationDefinition(
			RdbmsFilterInvocationDefinition rdbmsFilterInvocationDefinition) {
		this.rdbmsFilterInvocationDefinition = rdbmsFilterInvocationDefinition;
	}

	private List<RdbmsEntryHolder> getRdbmsEntryHolderList() {
		List<RdbmsEntryHolder> list = getRdbmsFilterInvocationDefinition()
				.execute();
		if(logger.isDebugEnabled()){
			for(RdbmsEntryHolder h:list){
				logger.debug(h);
			}
		}
		return list;
	}
}
